package us.icitap.cm.business.ejb;


import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import us.icitap.cm.business.AppListTypeEnum;
import us.icitap.cm.business.entities.AppList;
import us.icitap.cm.business.entities.AssociationType;
import us.icitap.cm.business.entities.Case;
import us.icitap.cm.business.entities.PoliceCode;
import us.icitap.cm.business.entities.ReportTypeEnum;
import us.icitap.cm.business.entities.UniqueNumber;
import us.icitap.cm.business.entities.regmin.Cities;
import us.icitap.cm.business.entities.regmin.District;
import us.icitap.cm.business.entities.regmin.VehicleModel;
import us.icitap.dao.PersistenceFacade;
import us.icitap.utils.Result;


@Stateless
public class AppPersistenceBean extends PersistenceFacade implements IAppPersistenceBean{

	@PersistenceContext(unitName="CaseManagement")
	EntityManager em;
	
	@Override
	public <T> Result<T> findEntityById(Object id, Class<T> entity) {
		// TODO Auto-generated method stub
		return super.findEntityById(id, entity, em);
	}
	
	@Override
	public Result<Case> findCaseById(String caseId){
		try {
			
			Case pCase = (Case) em.createQuery("Select o from Case o where o.caseId = :caseId").setParameter("caseId", caseId).getSingleResult();
			return new Result<Case>(pCase, true, null);
		}catch (NoResultException nre){
			return new Result<Case>(null, true, "Nuk ka ceshtje me kete numer");
		} catch (NonUniqueResultException nure){
			return new Result<Case>(null, false, "Ka me shume se nje ceshtje me kete numer");
		} catch (Exception e) {
			return new Result<Case>(null, false, e.getMessage());
		}
	}
	

	@Override
	public Result<List<AssociationType>> getAssociationType(String associationType){
		try {
			List<AssociationType> list = em.createQuery("Select o from AssociationType o where o.associationType = :associationType").setParameter("associationType", associationType).getResultList();
			return new Result<List<AssociationType>>(list, true, null);
		} catch (Exception e) {
			return new Result<List<AssociationType>>(null, false, e.getMessage());
		}
		
	}
	@Override
	public Result<List<Cities>> getCities(Object state){
		try {
			List<Cities> cities = em.createQuery("Select o from Cities o where o.states = :state order by o.tag ").setParameter("state", state).getResultList();
			return new Result<List<Cities>>(cities, true, null);
		} catch (Exception e) {
			return new Result<List<Cities>>(null, false, e.getMessage());
		}
	}
	
	@Override
	public Result<List<District>> getDistrict(Object region){
		try {
			List<District> districts = em.createQuery("Select o from District o where o.region = :region order by o.tag ").setParameter("region", region).getResultList();
			
			return new Result<List<District>>(districts, true, null);
		} catch (Exception e) {
			return new Result<List<District>>(null, false, e.getMessage());
		}
	}
	
	
	@Override
	public Result<List<VehicleModel>> getVehicleModel(Object brand){
		try {
			List<VehicleModel> vmList = em.createQuery("Select o from VehicleModel o where o.vehicleBrand = :vehicleBrand order by o.tag ").setParameter("vehicleBrand", brand).getResultList();
			return new Result<List<VehicleModel>>(vmList, true, null);
		} catch (Exception e) {
			return new Result<List<VehicleModel>>(null, false, e.getMessage());
		}
	}
	
	
	@Override
	public <T> Result<T> saveEntity(T entity) {
		// TODO Auto-generated method stub
		return super.saveEntity(entity, em);
	}
	
	@TransactionAttribute(TransactionAttributeType.MANDATORY)
	public String generateUNString(){

			Calendar c = Calendar.getInstance();

			String month = (new Integer(c.get(Calendar.MONTH) + 1)).toString();
			
			if(month.length()<2) month = "0" + month;
			
			String day = (new Integer(c.get(Calendar.DAY_OF_MONTH))).toString();
			
			if(day.length()<2) day = "0" + day;
			
			String date = c.get(Calendar.YEAR) + month + day;
			
			String sql = "select  MAX(SUBSTR(t.unique_number,9,4)) from mpc.unique_number  t where SUBSTR(t.unique_number,1,8) = '"+ date +"' ";
			
			Vector objects =  (Vector) em.createNativeQuery(sql).getResultList();
			 
			String max;
			Integer maxUN=0;
			
			if (objects == null || objects.isEmpty()) 
			{
				max= "0001";
				
			}
			else {
				if (objects.get(0) == null) max= "0001";
				else {
					maxUN = new Integer(objects.get(0).toString());
					maxUN  = maxUN + new Integer(1);
					if (maxUN > 999) {
						max=(new Integer(maxUN)).toString();
					}
					else if (maxUN >99 && maxUN <= 999) {
						max="0" + (new Integer(maxUN)).toString();
					}
					else if (maxUN >9 && maxUN <= 99) {
						max="00" + (new Integer(maxUN)).toString();
					}
					else {
						max="000" + (new Integer(maxUN)).toString();
					}
				}

			}
			
			return date + max;
					

	}
	
	@Override
	public Result<UniqueNumber> findUniqueNumber(String un){
		

		return this.findEntityById(un, UniqueNumber.class, em);
		
	}
	
	@Override
	public <T> Result<List<T>> getList(Class<T> entityClass,
			boolean withStatus, String orderBy) {
		
		return super.getList(entityClass, withStatus, orderBy, em);
	}
	
	@Override
	public Result<List<PoliceCode>> getRootPoliceCode(){
		try {
			List<PoliceCode> list = em.createQuery("Select o from PoliceCode o where o.superiorPoliceCode is null and o.status = :status").setParameter("status", true).getResultList();
			
			return new Result<List<PoliceCode>>(list, true, null);
		} catch (Exception e) {
			return new Result<List<PoliceCode>>(null, false, e.getMessage());
		}
		
	}
	
	@Override
	public Result<Case> saveReport(Case _case){
		try {
			_case.setRecordDate(new Date());
			
			_case.getLastReport().setRecordDate(new Date());
			if(_case.getLastReport().getReportType().equals(ReportTypeEnum.ER)){
				String un = this.generateUNString();
				_case.getLastReport().getEventReport().getUniqueNumber().setUniqueNumber(un);
				_case.setCaseId(un);
			}	
			Result<Case> result = this.saveEntity(_case);
			
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return new Result<Case>(null, false, e.getMessage());
		}
	}
	
	@Override
	public Integer getLastAppEntityId(Case pCase){
		try {
			Object lastId = em.createQuery("Select MAX(o.id) from AppEntity o where o.policeCase = :pCase").setParameter("pCase", pCase).getSingleResult();
			return (Integer)lastId;
		} catch (NoResultException nre) {
			return 0;
		}	catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	@Override
	public List<AppList> getAppList(AppListTypeEnum listType, boolean withStatus, boolean orderList){
		try {
			
			
			String sql = "Select o FROM AppList o WHERE o.appListType = :listType ";
			
			if (withStatus) {
				sql += " AND o.status = :status ";
				if(orderList)
					sql += " ORDER BY o.tag DESC";
				return em.createQuery(sql).setParameter("listType", listType).setParameter("status", true).getResultList();
			}

			if(orderList)
				sql += " ORDER BY o.tag DESC";
			return em.createQuery(sql).setParameter("listType", listType).getResultList();
			
			
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
	}
	
	@Override
	public Result<AppList> findAppListByTag(String tag){
		try {
			
			List<AppList> list = em.createQuery("SELECT o from AppList o WHERE o.tag = :tag").setParameter("tag", tag).getResultList();
			if(list != null && !list.isEmpty())
				return new Result<AppList>(list.get(0), true, null);
			
			return new Result<AppList>(null, true, "Nuk ka asnje rezultat");
			
		} catch (Exception e) {
			return new Result<AppList>(null, false, e.getMessage());
		}
	}
	
	@Override
	public Result<List<AppList>> getAppListChildren(AppList parent){
		try {
			List<AppList> list = em.createQuery("SELECT o from AppList o WHERE o.parent = :parent").setParameter("parent", parent).getResultList();
			return new Result<List<AppList>>(list, true, null);
			
		} catch (Exception e) {
			return new Result<List<AppList>>(null, false, e.getMessage());
		}
	}
	
}
